{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 重试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from rtsp.rtsp_server import setup_server\n",
    "#\n",
    "# setup_server()\n",
    "\n",
    "from retrying import retry\n",
    "import random\n",
    "import time\n",
    "\n",
    "\n",
    "def retry_if_error(exception):\n",
    "    return exception.__class__ in {ValueError, TimeoutError}\n",
    "\n",
    "\n",
    "def retry_if_not_result(result):\n",
    "    if result in [5, 10]:\n",
    "        print(\"result success {}\".format(result))\n",
    "        return False\n",
    "    else:\n",
    "        print('result retry {}'.format(result))\n",
    "        return True\n",
    "\n",
    "\n",
    "@retry(stop_max_attempt_number=50, wait_exponential_multiplier=1000, wait_exponential_max=60000,\n",
    "       retry_on_exception=retry_if_error)\n",
    "def foo():\n",
    "    print(int(time.time()), end=' ')\n",
    "    a = random.randint(1, 15)\n",
    "    if a >= 2:\n",
    "        print('Error {}'.format(a))\n",
    "        raise ValueError\n",
    "    print('success', a)\n",
    "\n",
    "\n",
    "@retry(retry_on_result=retry_if_not_result)\n",
    "def foo2():\n",
    "    print(int(time.time()), end=' ')\n",
    "    a = random.randint(1, 15)\n",
    "    return a\n",
    "\n",
    "\n",
    "# print(foo2())\n",
    "foo()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 超时控制\n",
    "\n",
    "实际项目中会涉及到需要对有些函数的响应时间做一些限制，如果超时就退出函数的执行，停止等待。\n",
    "\n",
    "可以利用python中的装饰器实现对函数执行时间的控制。\n",
    "\n",
    "## Unix 信号机制\n",
    "\n",
    "**限制：需要在linux系统上，并且必须在主线程中使用**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 有回调函数的超时报错装饰器\n",
    "import signal\n",
    "import time\n",
    "\n",
    "\n",
    "def set_timeout(num, callback):\n",
    "    def wrap(func):\n",
    "        def handle(\n",
    "                signum, frame\n",
    "        ):  # 收到信号 SIGALRM 后的回调函数，第一个参数是信号的数字，第二个参数是the interrupted stack frame.\n",
    "            raise RuntimeError\n",
    "\n",
    "        def to_do(*args, **kwargs):\n",
    "            try:\n",
    "                signal.signal(signal.SIGALRM, handle)  # 设置信号和回调函数\n",
    "                signal.alarm(num)  # 设置 num 秒的闹钟\n",
    "                print('start alarm signal.')\n",
    "                r = func(*args, **kwargs)\n",
    "                print('close alarm signal.')\n",
    "                signal.alarm(0)  # 关闭闹钟\n",
    "                return r\n",
    "            except RuntimeError as e:\n",
    "                callback()\n",
    "\n",
    "        return to_do\n",
    "\n",
    "    return wrap\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "\n",
    "    def after_timeout():  # 超时后的处理函数\n",
    "        print(\"函数超时\")\n",
    "\n",
    "    @set_timeout(2, after_timeout)  # 限时 2 秒\n",
    "    def connect():  # 要执行的函数\n",
    "        time.sleep(4)  # 函数执行时间，写大于2的值，可测试超时\n",
    "        print('函数正常执行')\n",
    "\n",
    "    connect()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## func_timeout\n",
    "\n",
    ">pip install func_timeout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "1\n",
      "1\n",
      "1\n",
      "1\n",
      "timeout!\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "from func_timeout import func_set_timeout, FunctionTimedOut\n",
    "\n",
    "\n",
    "@func_set_timeout(5)\n",
    "def f():\n",
    "    while True:\n",
    "        print(\"1\")\n",
    "        time.sleep(1)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    try:\n",
    "        f()\n",
    "    except FunctionTimedOut:\n",
    "        print(\"timeout!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## eventlet\n",
    "\n",
    ">pip install eventlet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1588942588\n",
      "1588942591\n",
      "over\n"
     ]
    }
   ],
   "source": [
    "import requests\n",
    "import eventlet\n",
    "import time\n",
    "\n",
    "eventlet.monkey_patch()\n",
    "\n",
    "time_limit = 3  #set timeout time 3s\n",
    "print(int(time.time()))\n",
    "with eventlet.Timeout(time_limit, False):\n",
    "    time.sleep(5)\n",
    "    r = requests.get(\"https://me.csdn.net/dcrmg\", verify=False)\n",
    "    print('ok')\n",
    "print(int(time.time()))\n",
    "print('over')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Timer\n",
    "\n",
    "- https://www.cnblogs.com/xueweihan/p/6653610.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1588943662\n",
      "1588943666\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Exception in thread Thread-5:\n",
      "Traceback (most recent call last):\n",
      "  File \"D:\\SoftInstall\\Anacoda3\\lib\\threading.py\", line 917, in _bootstrap_inner\n",
      "    self.run()\n",
      "  File \"D:\\SoftInstall\\Anacoda3\\lib\\threading.py\", line 1166, in run\n",
      "    self.function(*self.args, **self.kwargs)\n",
      "  File \"<ipython-input-17-eecf61e36e1b>\", line 9, in stop\n",
      "    raise RuntimeError\n",
      "RuntimeError\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from threading import Timer\n",
    "import time\n",
    "\n",
    "\n",
    "def set_timeout(num):\n",
    "    def wrap(func):\n",
    "        def stop():\n",
    "            print(int(time.time()))\n",
    "            raise RuntimeError\n",
    "\n",
    "        def to_do(*args, **kwargs):\n",
    "            # n 秒后执行\n",
    "            t = Timer(num, stop)\n",
    "            t.start()\n",
    "            r = func(*args, **kwargs)\n",
    "            t.cancel()\n",
    "            return r\n",
    "\n",
    "        return to_do\n",
    "\n",
    "    return wrap\n",
    "\n",
    "\n",
    "print(int(time.time()))\n",
    "try:\n",
    "\n",
    "    @set_timeout(4)\n",
    "    def foo():\n",
    "        time.sleep(6)\n",
    "except RuntimeError as e:\n",
    "    print('e', e)\n",
    "foo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "206.818px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
